package com.xiaoshuidi.cloud.module.report.service.finance;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.oss.core.OosFileService;
import com.xiaoshuidi.cloud.framework.security.core.LoginUser;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.module.contract.api.ContractTaxRateApi;
import com.xiaoshuidi.cloud.module.contract.vo.ContractTaxRateVO;
import com.xiaoshuidi.cloud.module.report.controller.finance.vo.ExportRespVO;
import com.xiaoshuidi.cloud.module.report.controller.finance.vo.SumIncomeExportRespVO;
import com.xiaoshuidi.cloud.module.report.controller.finance.vo.SumIncomePageReqVO;
import com.xiaoshuidi.cloud.module.report.controller.finance.vo.SumIncomePageRespVO;
import com.xiaoshuidi.cloud.module.report.convert.finance.IncomeSummaryConvert;
import com.xiaoshuidi.cloud.module.report.dal.DO.report.IncomeSummaryReportDO;
import com.xiaoshuidi.cloud.module.report.dal.mapper.report.IncomeSummaryReportMapper;
import com.xiaoshuidi.cloud.module.report.enums.ErrorCodeConstants;
import com.xiaoshuidi.cloud.module.report.framework.security.config.ConfigValues;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
@Slf4j
public class IncomeSummaryReportServiceImpl implements IncomeSummaryReportService {

    private final IncomeSummaryReportMapper incomeSummaryReportMapper;
    private final OosFileService oosFileService;
    private final ConfigValues configValues;
    @Resource
    private ContractTaxRateApi contractTaxRateApi;


    @Override
    public PageResult<SumIncomePageRespVO> totalIncomePage(SumIncomePageReqVO reqVO) {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if(loginUser==null){
            throw new ServiceException(ErrorCodeConstants.USER_NOT_LOGIN);
        }
        reqVO.setTenantId(loginUser.getTenantId());
        long num = incomeSummaryReportMapper.countListForPage(reqVO);
        List<IncomeSummaryReportDO> list = incomeSummaryReportMapper.selectListForPage(reqVO);
        list.forEach(item->{
            CommonResult<ContractTaxRateVO> contractTaxRate = contractTaxRateApi.getContractTaxRate(item.getApartmentId());
            ContractTaxRateVO data = contractTaxRate.getData();
            if(data != null){
                JSONArray objects = JSONUtil.parseArray(data.getContent());
                Map<String, List<Object>> type = objects.stream().collect(Collectors.groupingBy(json -> JSONUtil.parseObj(json.toString()).getStr("type")));
                //租金
                JSONObject rentIn = calculatedTax("租金", item.getRentIn(), type);
                item.setRentInVAT(rentIn.getBigDecimal("vat"));
                item.setRentInNotTax(rentIn.getBigDecimal("notTax"));

                //其他收入
                JSONObject otherIn = calculatedTax("其他收入", item.getRentIn(), type);
                item.setOtherInVAT(otherIn.getBigDecimal("vat"));
                item.setOtherInNotTax(otherIn.getBigDecimal("notTax"));

                //累计收入
                JSONObject sumIn = calculatedTax("累计收入", item.getRentIn(), type);
                item.setSumInVAT(sumIn.getBigDecimal("vat"));
                item.setSumInNotTax(sumIn.getBigDecimal("notTax"));

                //累计冷水费
                JSONObject sumColdWaterFee = calculatedTax("冷水费", item.getRentIn(), type);
                item.setSumColdWaterFeeVAT(sumColdWaterFee.getBigDecimal("vat"));
                item.setSumColdWaterFeeNotTax(sumColdWaterFee.getBigDecimal("notTax"));

                //累计热水费
                JSONObject sumHotWaterFee = calculatedTax("热水费", item.getRentIn(), type);
                item.setSumHotWaterFeeVAT(sumHotWaterFee.getBigDecimal("vat"));
                item.setSumHotWaterFeeNotTax(sumHotWaterFee.getBigDecimal("notTax"));

                //累计电费
                JSONObject sumElectricFee = calculatedTax("电费", item.getRentIn(), type);
                item.setSumElectricFeeVAT(sumElectricFee.getBigDecimal("vat"));
                item.setSumElectricFeeNotTax(sumElectricFee.getBigDecimal("notTax"));

                //累计物业费
                JSONObject sumPropertyFee = calculatedTax("物业费", item.getRentIn(), type);
                item.setSumPropertyFeeVAT(sumPropertyFee.getBigDecimal("vat"));
                item.setSumPropertyFeeNotTax(sumPropertyFee.getBigDecimal("notTax"));

                //累计维修费
                JSONObject sumMaintenanceFee = calculatedTax("维修费", item.getRentIn(), type);
                item.setSumMaintenanceFeeVAT(sumMaintenanceFee.getBigDecimal("vat"));
                item.setSumMaintenanceFeeNotTax(sumMaintenanceFee.getBigDecimal("notTax"));

                //累计 保洁费
                JSONObject sumCleanFee = calculatedTax("清洁费", item.getRentIn(), type);
                item.setSumCleanFeeVAT(sumCleanFee.getBigDecimal("vat"));
                item.setSumCleanFeeNotTax(sumCleanFee.getBigDecimal("notTax"));

                //累计换房费
                JSONObject sumHouseTransferFee = calculatedTax("换房费", item.getRentIn(), type);
                item.setSumHouseTransferFeeVAT(sumHouseTransferFee.getBigDecimal("vat"));
                item.setSumHouseTransferFeeNotTax(sumHouseTransferFee.getBigDecimal("notTax"));

                //累计违约金
                JSONObject sumLiquidatedFee = calculatedTax("违约金", item.getRentIn(), type);
                item.setSumLiquidatedFeeVAT(sumLiquidatedFee.getBigDecimal("vat"));
                item.setSumLiquidatedFeeNotTax(sumLiquidatedFee.getBigDecimal("notTax"));

                //累计延期住宿费
                JSONObject sumDelayFee = calculatedTax("延期住宿费", item.getRentIn(), type);
                item.setSumDelayFeeVAT(sumDelayFee.getBigDecimal("vat"));
                item.setSumDelayFeeNotTax(sumDelayFee.getBigDecimal("notTax"));

                //累计赔偿金
                JSONObject sumDamages = calculatedTax("赔偿金", item.getRentIn(), type);
                item.setSumDamagesVAT(sumDamages.getBigDecimal("vat"));
                item.setSumDamagesNotTax(sumDamages.getBigDecimal("notTax"));

                //累计滞纳金金
                JSONObject sumLateFee = calculatedTax("滞纳金", item.getRentIn(), type);
                item.setSumLateFeeVAT(sumLateFee.getBigDecimal("vat"));
                item.setSumLateFeeNotTax(sumLateFee.getBigDecimal("notTax"));
            }else {
                //租金
                item.setRentInVAT(new BigDecimal(0));
                item.setRentInNotTax(item.getRentIn());
                //其他收入
                item.setOtherInVAT(new BigDecimal(0));
                item.setOtherInNotTax(item.getOtherIn());
                //累计收入
                item.setSumInVAT(new BigDecimal(0));
                item.setSumInNotTax(item.getSumIn());
                //累计冷水费
                item.setSumColdWaterFeeVAT(new BigDecimal(0));
                item.setSumColdWaterFeeNotTax(item.getSumColdWaterFee());
                //累计热水费
                item.setSumHotWaterFeeVAT(new BigDecimal(0));
                item.setSumHotWaterFeeNotTax(item.getSumHotWaterFee());
                //累计电费
                item.setSumElectricFeeVAT(new BigDecimal(0));
                item.setSumElectricFeeNotTax(item.getSumElectricFee());
                //累计物业费
                item.setSumPropertyFeeVAT(new BigDecimal(0));
                item.setSumPropertyFeeNotTax(item.getSumPropertyFee());
                //累计维修费
                item.setSumMaintenanceFeeVAT(new BigDecimal(0));
                item.setSumMaintenanceFeeNotTax(item.getSumMaintenanceFee());
                //累计 保洁费
                item.setSumCleanFeeVAT(new BigDecimal(0));
                item.setSumCleanFeeNotTax(item.getSumCleanFee());
                //累计换房费
                item.setSumHouseTransferFeeVAT(new BigDecimal(0));
                item.setSumHouseTransferFeeNotTax(item.getSumHouseTransferFee());
                //累计违约金
                item.setSumLiquidatedFeeVAT(new BigDecimal(0));
                item.setSumLiquidatedFeeNotTax(item.getSumLiquidatedFee());
                //累计延期住宿费
                item.setSumDelayFeeVAT(new BigDecimal(0));
                item.setSumDelayFeeNotTax(item.getSumDelayFee());
                //累计赔偿金
                item.setSumDamagesVAT(new BigDecimal(0));
                item.setSumDamagesNotTax(item.getSumDamages());
                //累计滞纳金金
                item.setSumLateFeeVAT(new BigDecimal(0));
                item.setSumLateFeeNotTax(item.getSumLateFee());
            }
        });
        List<SumIncomePageRespVO> respVOS = IncomeSummaryConvert.INSTANCE.convertSumIncomeListForPage(list);
        return new PageResult<>(respVOS, num);
    }

    /**
     * 计算税率
     * @param text
     * @param money
     * @param type
     * @return
     */
    private JSONObject calculatedTax(String text,BigDecimal money,Map<String, List<Object>> type){
        JSONObject entries = new JSONObject();
        if (type.containsKey(text)) {
            JSONArray objects = JSONUtil.parseArray(type.get(text));
            JSONObject jsonObject = objects.getJSONObject(0);
            BigDecimal taxRate = jsonObject.getBigDecimal("taxRate");
            BigDecimal vat = money.multiply(taxRate).setScale(2, BigDecimal.ROUND_HALF_UP);
            BigDecimal notTax = money.subtract(vat);
            entries.putOpt("vat",vat);
            entries.putOpt("notTax",notTax);
        }else{
            entries.putOpt("vat","0");
            entries.putOpt("notTax",money);
        }
        return entries;
    }

    @Override
    public ExportRespVO sumIncomeExport(SumIncomePageReqVO req) {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if(loginUser==null){
            throw new ServiceException(ErrorCodeConstants.USER_NOT_LOGIN);
        }
        req.setTenantId(loginUser.getTenantId());
        String startDate = req.getStartDate();
        String endDate =req.getEndDate();
        String fileName = "";
        if(startDate.equals(endDate)){
            fileName = startDate + "收入汇总表.xlsx";
        }else {
            fileName = startDate+"~"+endDate + "收入汇总表.xlsx";
        }
        String filePath = configValues.getNfsPath() + File.separator +fileName;
        ExcelWriter excelWriter = EasyExcel.write(filePath, SumIncomeExportRespVO.class).build();
        WriteSheet sheet = EasyExcel.writerSheet("sheet1").build();
        List<IncomeSummaryReportDO> list = incomeSummaryReportMapper.selectListForExport(req);
        if(CollectionUtils.isEmpty(list)){
            throw new ServiceException(ErrorCodeConstants.SUMMARY_INCOME_NOT_EXISTS);
        }
        List<SumIncomeExportRespVO> respVOS = IncomeSummaryConvert.INSTANCE.convertSumIncomeListForExport(list);
        excelWriter.write(respVOS, sheet);
        excelWriter.finish();
        //上传到oos返回URL
        String url = oosFileService.oosUploadFile(new File(filePath));
        ExportRespVO resp = new ExportRespVO();
        if(url.startsWith("http:")){
            url = url.replace("http:","https:");
        }
        resp.setUrl(url);
        resp.setFileName(fileName);
        return resp;
    }

    @Override
    public List<IncomeSummaryReportDO> selectSumByCurrentMonth(String currentMonth) {
        LambdaQueryWrapper<IncomeSummaryReportDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IncomeSummaryReportDO::getStatisticsMonth,currentMonth);
        return incomeSummaryReportMapper.selectList(queryWrapper);
    }

    @Override
    public void batchInsert(List<IncomeSummaryReportDO> list) {
        incomeSummaryReportMapper.insertBatch(list);
    }
    @Override
    public void batchUpdate(List<IncomeSummaryReportDO> list) {
        incomeSummaryReportMapper.updateBatch(list, list.size());
    }
}
